#!/usr/bin/env python3
"""
优化的配置模块
实现懒加载、预验证和性能优化
"""

import os
import sys
import json
import time
import psutil
from typing import List, Dict, Any, Optional, Callable
from dataclasses import dataclass, field
from pathlib import Path
from functools import lru_cache
import threading


@dataclass
class SystemResources:
    """系统资源信息"""
    cpu_count: int
    total_memory_mb: int
    available_memory_mb: int
    cpu_usage_percent: float
    memory_usage_percent: float
    
    @classmethod
    def get_current(cls) -> 'SystemResources':
        """获取当前系统资源"""
        return cls(
            cpu_count=os.cpu_count() or 4,
            total_memory_mb=psutil.virtual_memory().total // 1024 // 1024,
            available_memory_mb=psutil.virtual_memory().available // 1024 // 1024,
            cpu_usage_percent=psutil.cpu_percent(),
            memory_usage_percent=psutil.virtual_memory().percent
        )
    
    def recommend_max_workers(self) -> int:
        """推荐的最大工作线程数"""
        # 基于CPU核心数和内存使用率
        base_workers = min(self.cpu_count, 8)
        
        # 如果内存使用率过高，减少线程数
        if self.memory_usage_percent > 80:
            base_workers = max(2, base_workers // 2)
        elif self.memory_usage_percent > 60:
            base_workers = max(2, int(base_workers * 0.7))
        
        return base_workers
    
    def recommend_batch_size(self) -> int:
        """推荐的批处理大小"""
        # 基于可用内存
        if self.available_memory_mb > 8000:  # > 8GB
            return 100
        elif self.available_memory_mb > 4000:  # > 4GB
            return 50
        elif self.available_memory_mb > 2000:  # > 2GB
            return 25
        else:
            return 10


@dataclass
class PerformanceConfig:
    """性能配置"""
    enable_cache: bool = True
    cache_ttl: int = 3600  # 缓存有效期（秒）
    cache_dir: str = "/tmp/git_pull_cache"
    enable_parallel_scan: bool = True
    scan_batch_size: int = 100
    enable_batch_processing: bool = True
    processing_batch_size: int = 10
    enable_streaming: bool = True
    stream_buffer_size: int = 1000
    enable_auto_scaling: bool = True
    min_workers: int = 2
    max_workers: int = 8
    target_cpu_usage: float = 70.0
    target_memory_usage: float = 80.0
    enable_retry: bool = True
    max_retries: int = 3
    retry_delay: float = 1.0
    enable_progress: bool = True
    progress_update_interval: float = 1.0
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            'enable_cache': self.enable_cache,
            'cache_ttl': self.cache_ttl,
            'cache_dir': self.cache_dir,
            'enable_parallel_scan': self.enable_parallel_scan,
            'scan_batch_size': self.scan_batch_size,
            'enable_batch_processing': self.enable_batch_processing,
            'processing_batch_size': self.processing_batch_size,
            'enable_streaming': self.enable_streaming,
            'stream_buffer_size': self.stream_buffer_size,
            'enable_auto_scaling': self.enable_auto_scaling,
            'min_workers': self.min_workers,
            'max_workers': self.max_workers,
            'target_cpu_usage': self.target_cpu_usage,
            'target_memory_usage': self.target_memory_usage,
            'enable_retry': self.enable_retry,
            'max_retries': self.max_retries,
            'retry_delay': self.retry_delay,
            'enable_progress': self.enable_progress,
            'progress_update_interval': self.progress_update_interval
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'PerformanceConfig':
        """从字典创建"""
        return cls(**data)


class OptimizedConfiguration:
    """优化的配置管理器"""
    
    def __init__(self, 
                 root_directory: str = ".",
                 include_patterns: Optional[List[str]] = None,
                 exclude_patterns: Optional[List[str]] = None,
                 verbose: bool = False,
                 dry_run: bool = False,
                 timeout: int = 300,
                 max_workers: Optional[int] = None,
                 config_file: Optional[str] = None):
        """
        初始化优化的配置
        
        Args:
            root_directory: 根目录
            include_patterns: 包含模式
            exclude_patterns: 排除模式
            verbose: 详细输出
            dry_run: 预览模式
            timeout: 超时时间
            max_workers: 最大工作线程数
            config_file: 配置文件路径
        """
        # 基本配置
        self.root_directory = root_directory
        self.include_patterns = include_patterns or []
        self.exclude_patterns = exclude_patterns or []
        self.verbose = verbose
        self.dry_run = dry_run
        self.timeout = timeout
        
        # 延迟加载的字段
        self._max_workers = max_workers
        self._system_resources: Optional[SystemResources] = None
        self._performance_config: Optional[PerformanceConfig] = None
        
        # 配置文件
        self.config_file = config_file or os.path.expanduser("~/.git_pull_config.json")
        
        # 验证状态
        self._is_valid = False
        self._error_message = ""
        self._validation_thread = None
        self._validation_complete = threading.Event()
        
        # 性能统计
        self.access_stats = {
            'cache_hits': 0,
            'cache_misses': 0,
            'validation_time': 0.0
        }
        
        # 异步预验证
        self._start_background_validation()
    
    def _start_background_validation(self):
        """启动后台验证"""
        def validate():
            start_time = time.time()
            try:
                # 执行验证
                self._validate_config()
                self.access_stats['validation_time'] = time.time() - start_time
            finally:
                self._validation_complete.set()
        
        self._validation_thread = threading.Thread(target=validate)
        self._validation_thread.daemon = True
        self._validation_thread.start()
    
    @property
    def max_workers(self) -> int:
        """获取最大工作线程数（懒加载）"""
        if self._max_workers is None:
            # 获取系统资源并推荐线程数
            resources = self.system_resources
            self._max_workers = resources.recommend_max_workers()
        return self._max_workers
    
    @property
    def system_resources(self) -> SystemResources:
        """获取系统资源信息（懒加载）"""
        if self._system_resources is None:
            self._system_resources = SystemResources.get_current()
        return self._system_resources
    
    @property
    def performance_config(self) -> PerformanceConfig:
        """获取性能配置（懒加载）"""
        if self._performance_config is None:
            self._performance_config = self._load_performance_config()
        return self._performance_config
    
    def _load_performance_config(self) -> PerformanceConfig:
        """加载性能配置"""
        # 默认配置
        config = PerformanceConfig()
        
        # 从配置文件加载
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    if 'performance' in data:
                        config = PerformanceConfig.from_dict(data['performance'])
            except Exception as e:
                if self.verbose:
                    print(f"加载性能配置失败: {e}")
        
        # 根据系统资源调整
        resources = self.system_resources
        
        # 调整线程数
        if self._max_workers is None:
            config.max_workers = resources.recommend_max_workers()
        else:
            config.max_workers = self._max_workers
        
        # 调整批处理大小
        config.scan_batch_size = resources.recommend_batch_size()
        config.processing_batch_size = max(1, config.scan_batch_size // 10)
        
        return config
    
    def wait_validation(self, timeout: Optional[float] = None) -> bool:
        """
        等待验证完成
        
        Args:
            timeout: 超时时间
            
        Returns:
            bool: 验证是否完成
        """
        return self._validation_complete.wait(timeout)
    
    @property
    def is_valid(self) -> bool:
        """配置是否有效"""
        self.wait_validation()
        return self._is_valid
    
    @property
    def error_message(self) -> str:
        """错误消息"""
        self.wait_validation()
        return self._error_message
    
    def _validate_config(self):
        """验证配置"""
        try:
            # 验证根目录
            if not self.root_directory:
                self._error_message = "目录不能为空"
                return
            
            root_path = Path(self.root_directory)
            if not root_path.exists():
                self._error_message = f"不存在的目录: {self.root_directory}"
                return
            
            if not root_path.is_dir():
                self._error_message = f"路径不是目录: {self.root_directory}"
                return
            
            # 验证超时时间
            if self.timeout <= 0:
                self._error_message = "超时时间必须大于0"
                return
            
            # 验证工作线程数
            if self.max_workers <= 0:
                self._error_message = "工作线程数必须大于0"
                return
            
            # 验证模式
            for pattern in self.include_patterns + self.exclude_patterns:
                if not isinstance(pattern, str):
                    self._error_message = "模式必须是字符串"
                    return
            
            # 验证性能配置
            perf_config = self.performance_config
            if perf_config.max_workers < perf_config.min_workers:
                self._error_message = "最大工作线程数不能小于最小工作线程数"
                return
            
            # 创建缓存目录
            if perf_config.enable_cache:
                os.makedirs(perf_config.cache_dir, exist_ok=True)
            
            self._is_valid = True
            self._error_message = ""
            
        except Exception as e:
            self._error_message = f"配置验证失败: {str(e)}"
            self._is_valid = False
    
    @lru_cache(maxsize=1000)
    def should_include_repository(self, repo_path: str) -> bool:
        """
        检查仓库是否应该被包含（带缓存）
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            bool: 是否应该包含
        """
        if not self.include_patterns:
            self.access_stats['cache_hits'] += 1
            return True
        
        self.access_stats['cache_misses'] += 1
        repo_name = os.path.basename(repo_path)
        
        for pattern in self.include_patterns:
            if self._match_pattern(repo_name, pattern):
                return True
        
        return False
    
    @lru_cache(maxsize=1000)
    def should_exclude_repository(self, repo_path: str) -> bool:
        """
        检查仓库是否应该被排除（带缓存）
        
        Args:
            repo_path: 仓库路径
            
        Returns:
            bool: 是否应该排除
        """
        if not self.exclude_patterns:
            self.access_stats['cache_hits'] += 1
            return False
        
        self.access_stats['cache_misses'] += 1
        repo_name = os.path.basename(repo_path)
        
        for pattern in self.exclude_patterns:
            if self._match_pattern(repo_name, pattern):
                return True
        
        return False
    
    def _match_pattern(self, text: str, pattern: str) -> bool:
        """
        模式匹配（优化版本）
        
        Args:
            text: 文本
            pattern: 模式
            
        Returns:
            bool: 是否匹配
        """
        # 简单的字符串包含检查（对于常见模式更快）
        if '*' not in pattern and '?' not in pattern:
            return pattern in text
        
        # 使用 fnmatch 处理复杂模式
        import fnmatch
        return fnmatch.fnmatch(text, pattern)
    
    def get_summary(self) -> str:
        """
        获取配置摘要
        
        Returns:
            str: 配置摘要
        """
        self.wait_validation()
        
        # 获取性能配置
        perf_config = self.performance_config
        
        summary_parts = [
            f"根目录: {self.root_directory}",
            f"包含模式: {self.include_patterns}",
            f"排除模式: {self.exclude_patterns}",
            f"详细输出: {self.verbose}",
            f"预览模式: {self.dry_run}",
            f"超时时间: {self.timeout}秒",
            f"最大线程数: {self.max_workers}",
            f"配置有效: {self._is_valid}"
        ]
        
        # 添加性能配置信息
        if self.verbose:
            summary_parts.extend([
                f"缓存启用: {perf_config.enable_cache}",
                f"并行扫描: {perf_config.enable_parallel_scan}",
                f"批处理: {perf_config.enable_batch_processing}",
                f"流式处理: {perf_config.enable_streaming}",
                f"自动扩缩: {perf_config.enable_auto_scaling}",
                f"重试机制: {perf_config.enable_retry}"
            ])
        
        if self._error_message:
            summary_parts.append(f"错误: {self._error_message}")
        
        return " | ".join(summary_parts)
    
    def get_performance_summary(self) -> Dict[str, Any]:
        """
        获取性能摘要
        
        Returns:
            Dict[str, Any]: 性能摘要
        """
        resources = self.system_resources
        perf_config = self.performance_config
        
        return {
            'system_resources': {
                'cpu_count': resources.cpu_count,
                'total_memory_mb': resources.total_memory_mb,
                'available_memory_mb': resources.available_memory_mb,
                'cpu_usage_percent': resources.cpu_usage_percent,
                'memory_usage_percent': resources.memory_usage_percent
            },
            'performance_config': perf_config.to_dict(),
            'access_stats': self.access_stats,
            'cache_efficiency': (
                self.access_stats['cache_hits'] / 
                (self.access_stats['cache_hits'] + self.access_stats['cache_misses'])
                if (self.access_stats['cache_hits'] + self.access_stats['cache_misses']) > 0 else 0
            )
        }
    
    def save_config(self, file_path: Optional[str] = None):
        """
        保存配置到文件
        
        Args:
            file_path: 文件路径
        """
        if file_path is None:
            file_path = self.config_file
        
        config_data = {
            'basic': {
                'root_directory': self.root_directory,
                'include_patterns': self.include_patterns,
                'exclude_patterns': self.exclude_patterns,
                'verbose': self.verbose,
                'dry_run': self.dry_run,
                'timeout': self.timeout,
                'max_workers': self.max_workers
            },
            'performance': self.performance_config.to_dict()
        }
        
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=2, ensure_ascii=False)
            
            if self.verbose:
                print(f"配置已保存到: {file_path}")
                
        except Exception as e:
            print(f"保存配置失败: {e}")
    
    def optimize_for_environment(self):
        """根据环境优化配置"""
        resources = self.system_resources
        perf_config = self.performance_config
        
        # 根据系统资源调整
        if resources.memory_usage_percent > 80:
            # 内存紧张，减少缓冲区大小
            perf_config.stream_buffer_size = max(100, perf_config.stream_buffer_size // 2)
            perf_config.scan_batch_size = max(10, perf_config.scan_batch_size // 2)
        
        if resources.cpu_usage_percent > 80:
            # CPU 紧张，减少线程数
            perf_config.max_workers = max(2, perf_config.max_workers // 2)
        
        # 根据仓库数量调整
        # 这里可以添加更多的自适应逻辑
        
        if self.verbose:
            print("配置已根据系统环境优化")


def test_optimized_config():
    """测试优化的配置"""
    print("测试优化的配置...")
    
    # 创建配置
    config = OptimizedConfiguration(
        root_directory=".",
        include_patterns=["*project*"],
        exclude_patterns=["*test*"],
        verbose=True
    )
    
    # 等待验证完成
    print("等待验证...")
    config.wait_validation()
    
    print(f"配置有效: {config.is_valid}")
    print(f"错误信息: {config.error_message}")
    
    # 打印摘要
    print("\n配置摘要:")
    print(config.get_summary())
    
    # 打印性能摘要
    print("\n性能摘要:")
    perf_summary = config.get_performance_summary()
    print(f"系统资源: CPU={perf_summary['system_resources']['cpu_count']} "
          f"内存={perf_summary['system_resources']['total_memory_mb']}MB")
    print(f"缓存效率: {perf_summary['cache_efficiency']:.2%}")
    
    # 测试仓库过滤
    print("\n测试仓库过滤:")
    test_paths = [
        "/path/to/my_project",
        "/path/to/test_project",
        "/path/to/other_repo"
    ]
    
    for path in test_paths:
        include = config.should_include_repository(path)
        exclude = config.should_exclude_repository(path)
        print(f"  {path}: 包含={include}, 排除={exclude}")
    
    # 测试配置保存
    print("\n测试配置保存...")
    config.save_config("/tmp/test_config.json")
    
    # 测试环境优化
    print("\n测试环境优化...")
    config.optimize_for_environment()
    
    print("测试完成!")


if __name__ == "__main__":
    test_optimized_config()